﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using System.Xml.Linq;
using DataMonitor.Logging;
using DataMonitor.Model;
using IDataMonitor;
namespace DataMonitor
{
    public partial class FormMain : Form
    {
        private readonly Action<string> _addMsgDelegate;
        private List<DllBase> _userdlls = new List<DllBase>();
        public FormMain()
        {
            InitializeComponent();
            _addMsgDelegate = AddMsg;
        }
        private void FormMain_Load(object sender, EventArgs e)
        {
            Text = ConfigHelper.GetValue("AppName");
            InitDevices();
        }
        private void InitDevices()
        {
            var root = XElement.Load("net.xml");
            foreach (var xElement in root.Elements("device"))
            {
                MonitorBase monitor = null;
                if (xElement.Attribute("type").Value == "net")
                {
                    string ip = xElement.Attribute("ip").Value;
                    ushort port = ushort.Parse(xElement.Attribute("port").Value);
                    monitor = new TcpMonitor(ip, port) { ShowMsgAction = AddMsg };
                }
                else if (xElement.Attribute("type").Value == "serialport")
                {
                    string name = xElement.Attribute("name").Value;
                    int baudrate = ushort.Parse(xElement.Attribute("baudrate").Value);
                    monitor = new SerialportMonitor(name, baudrate) { ShowMsgAction = AddMsg };
                }
                if (monitor != null)
                {
                    string dllpath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + xElement.Attribute("dll").Value;
                    try
                    {
                        var assembly = Assembly.LoadFile(dllpath);
                        foreach (var type in assembly.GetTypes())
                        {
                            if (!type.IsClass || type.IsNotPublic) continue;
                            if (type.BaseType == typeof(DllBase))
                            {
                                var obj = Activator.CreateInstance(type) as DllBase;
                                obj.SendFunc = monitor.Send;
                                monitor.ReceiveEvent += obj.OnReceive;
                                _userdlls.Add(obj);
                                obj.DllLoad();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Log4NetAdapter.Instance.Write(e);
                    }
                }
            }
        }
        void AddMsg(string msg)
        {
            if (lbxMsg.InvokeRequired)
            {
                lbxMsg.Invoke(_addMsgDelegate, msg);
            }
            else
            {
                if (lbxMsg.Items.Count > 100)
                {
                    lbxMsg.Items.RemoveAt(0);
                }
                lbxMsg.Items.Add(msg);
                lbxMsg.TopIndex = lbxMsg.Items.Count - lbxMsg.Height / lbxMsg.ItemHeight;
            }
        }
        private void FormMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            _userdlls.ForEach(dll => dll.DllUnload());
        }
    }
}
